
import { _decorator, assetManager, builtinResMgr, Component, director, game, Label, Node, NodeEventType, Prefab, ProgressBar, Sprite, SpriteFrame, sys, tween, UIRenderer, Vec3 } from 'cc';
import { BaseEventName, LoadingProcess } from './scripts/framework/config/Appcfg';
import { AudioMgr } from './scripts/framework/manager/AudioMgr';
import { EventMgr } from './scripts/framework/manager/EventMgr';
import { LogMgr } from './scripts/framework/manager/LogMgr';
import { PlatformManager } from './scripts/framework/manager/PlatformManager';
import { ResCacheMgr } from './scripts/framework/manager/ResCacheMgr';
import { ResourceMgr } from './scripts/framework/manager/ResourceMgr';
import { SDKMgr } from './scripts/framework/manager/SDKMgr';
import { UIMgr } from './scripts/framework/manager/UIMgr';
import { TimeUtils } from './scripts/framework/utils/TimeUtils';
import { AudioCF, UICF } from './scripts/game/config/Config';
import { DataMgr } from './scripts/game/manager/DataMgr';
import { PlayerMgr } from './scripts/game/manager/PlayerMgr';
const { ccclass, property } = _decorator;

const nodeEventRegistry = new WeakMap<Node, Map<symbol, {
    type: NodeEventType;
    callback: Function;
    target: any;
    args: any[];
}>>();


@ccclass('Load')
export class Load extends Component {
    @property(Node)
    uiRoot: Node = null;
    @property(ProgressBar)
    progressBar: ProgressBar = null;
    @property(Label)
    tips: Label = null;
    private sceneName: string = "Main"

    private process: number = 0;
    onLoad() {
        this.initYQ()
        //渠道sdk初始化
        PlatformManager.getInstance().init();
        ResCacheMgr.getInstance().init()
        UIMgr.getInstance().addUICnf(UICF)
        UIMgr.getInstance().Init(this.uiRoot)
        //初始化音频管理器
        AudioMgr.getInstance().init(AudioCF)

        // game.frameRate = 30
    }
    start() {
        // macro.CLEANUP_IMAGE_CACHE = false;
        // DynamicAtlasManager.instance.enabled = true;
        director.preloadScene(this.sceneName)
        game.addPersistRootNode(this.uiRoot)
        this.progressBar.progress = 0
        EventMgr.getInstance().on(BaseEventName.Loading, this, this.setProcessLoad)
        //加载花边框的资源

        this.setProcessLoad(LoadingProcess.StartLoading)
        // UIMgr.getInstance().openUI(UIID.UShowILayer3D, UIID.Default);
    }
    //加载花边框的资源

    setProcessLoad(process: number) {
        this.process = process / 100;
        switch (process) {
            case LoadingProcess.StartLoading:
                this.tips.string = "配置文件加载";
                DataMgr.getInstance().preload();
                break
            case LoadingProcess.ExcelCfg:
                LogMgr.getInstance().debug("加载用户数据")
                this.tips.string = "加载用户数据";
                PlayerMgr.getInstance().preload();
                break;
            case LoadingProcess.PlayerCfg:
                this.tips.string = "进入中...";
                this.tips.string = "加载UI界面";
                // UIMgr.getInstance().preLoadUI(UIID.UIHome, () => {
                //     this.setProcessLoad(LoadingProcess.UICfg)
                // });
                // UIMgr.getInstance().preLoadUI(UIID.UIMoney, () => {
                this.setProcessLoad(LoadingProcess.UICfg)
                // });
                break
            case LoadingProcess.UICfg:
                this.tips.string = "加载资源";
                ResourceMgr.getInstance().loadBundle("prefabs", () => {
                    ResourceMgr.getInstance().preload("prefabs", ["UIHome"]);
                    this.setProcessLoad(LoadingProcess.ResCfg)
                })
                // ResourceMgr.getInstance().preload("prefabs", ["UIMoney"]);
                break
            case LoadingProcess.ResCfg:
                this.tips.string = "加载完成";
                this.setProcessLoad(LoadingProcess.EndLoading)
                break
            case LoadingProcess.EndLoading:

                if (!TimeUtils.compareIsToday(PlayerMgr.getInstance().getUserData().getonlyOverTime())) {
                    let _pm = PlayerMgr.getInstance().getUserData()
                    _pm.SetDayShare(false)
                    _pm.SetDayCircle(false)
                }
                PlayerMgr.getInstance().getUserData().setonlyTime(TimeUtils.GetTimeBySecond())
                PlayerMgr.instance.uid = this.generateUID();
                SDKMgr.getInstance().login((code) => {
                    if (code === 404) {
                        this.initScene(this.generateUID())
                        return
                    }
                    SDKMgr.getInstance().switchGameConfig(() => {
                        // director.loadScene(this.sceneName);
                        this.initScene(PlayerMgr.instance.uid)
                    });
                })
                break;
        }
        this.progressBar.progress = this.process
    }
    initScene(uid) {
        // let loadSceneName = PlayerMgr.getInstance().getUserData().getLevel()===1?'ui/UIGame':'ui/UIHome';
        let loadSceneName = "ui/UIGame";
        console.log("PlayerMgr.getInstance().getUserData().getLevel", PlayerMgr.getInstance().getUserData(), loadSceneName)

        // HttpMgr.getInstance().getUserData(PlayerMgr.instance.uid, (isSucc, data) => {
        //     if (data) {
        //         PlayerMgr.instance.isCanSave = true;
        //         PlayerMgr.instance.userCloudData = data;
        //         this.intoScene('ui/UIHome')
        //     } else {
        //         this.intoScene(loadSceneName)
        //         console.log("无该请求")
        //     }
        // }, () => {
        //     this.intoScene(loadSceneName)
        //     console.log("网咯请求失败")
        // })
        this.intoScene(loadSceneName)
        // console.log("进入中...",PlayerMgr.getInstance().getUserData().data)
    }
    intoScene(loadSceneName: string) {
        let prefabs = assetManager.getBundle("prefabs")
        prefabs.load(loadSceneName, Prefab, (err, assets) => {
            if (err) {
                LogMgr.getInstance().error("prefabs")
                return
            }
            director.loadScene(this.sceneName);
        })
    }
    generateUID() {
        // 获取设备信息
        const deviceInfo: DeviceInfo = {
            userAgent: navigator.userAgent,
            screenWidth: window.screen.width,
            screenHeight: window.screen.height,
            language: navigator.language
        };

        // 将设备信息转换为字符串
        const deviceInfoString = JSON.stringify(deviceInfo);

        // 使用SHA-256哈希算法生成哈希值
        const hash = this.sha256(deviceInfoString);

        // 取哈希值的前16位作为UID
        const uid = hash.slice(0, 16);

        console.log("deviceInfo", uid)
        return uid
    }
    sha256(str: string): string {
        try {

            return window['CryptoJS'].SHA256(str).toString();
        } catch {
            return "zxchuias"
        }
    }

    initYQ() {
        Node.prototype.skin = function (url: string, bundleName: string, callback?: Function, ...args) {
            let sprite = this.getComponent(Sprite) as Sprite;
            var _url = url as any;
            if (!sprite) {
                this.addComponent(Sprite);
                sprite = this.getComponent(Sprite);
            }
            if (url == "") {
                sprite.spriteFrame = null;
                return;
            }
            let bundle = bundleName ? assetManager.getBundle(bundleName) : assetManager.getBundle("resources");
            if (bundle) {
                bundle.load(_url + "/spriteFrame", SpriteFrame, (err, spriteFrame) => {
                    if (err) {
                        sprite.spriteFrame = null;
                        console.warn(`${bundleName}目录下的资源加载失败`, url);
                        return;
                    }
                    callback && callback(...args, spriteFrame);
                    sprite.spriteFrame = spriteFrame;
                });
            } else {
                // console.error("bundleName 不存在")
                assetManager.loadBundle(bundleName, (err, bundle) => {
                    if (err) {
                        console.warn(`${bundleName}目录下的资源加载失败`, url);
                        return;
                    }
                    bundle.load(_url + "/spriteFrame", SpriteFrame, (err, spriteFrame) => {
                        if (err) {
                            sprite.spriteFrame = null;
                            console.warn(`${bundleName}目录下的资源加载失败`, url);
                            return;
                        }
                        callback && callback(...args, spriteFrame);
                        sprite.spriteFrame = spriteFrame;
                    });
                });
            }
        }
        Object.defineProperty(Node.prototype, '_zindex', {
            value: 0,
            writable: true,
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, 'zIndex', {
            get: function () {
                return this._zindex;
            },
            set: function (value: number) {
                this._zindex = value;
                let children = this.parent.children;
                children.sort((a, b) => a._zindex - b._zindex);

                //这一段加了感觉和没加是一样的
                for (let i = 0; i < children.length; i++) {
                    children[i].siblingIndex = i;
                }
            },
            enumerable: true,
            configurable: true
        });
        this.node.zIndex = 10
        Node.prototype.setGray = function (isGray) {
            if (this == null || this.isValid == false) {
                return;
            }
            let material = builtinResMgr.get(isGray ? "ui-sprite-gray-material" : "");
            let renders = this.getComponentsInChildren(UIRenderer);
            for (let i = 0; i < renders.length; i++) {
                renders[i].customMaterial = material;
            }
        }
        Node.prototype.onClick = function (callback: Function, target?: any, ...args: any) {
            this.eventMap = this.eventMap || new Map();
            // 添加唯一标识作为键，防止匿名函数重复
            const eventKey = callback.name || Symbol('eventKey');
            if (!this.eventMap.has(eventKey)) {
                // 存储完整的处理器对象
                this.eventMap.set(eventKey, {
                    callback,
                    target: target || this, // 默认使用当前节点作为 target
                    args: args || []
                });
                this.on('click', (event) => {
                    const handler = this.eventMap.get(eventKey);
                    if (!handler) {
                        console.warn('Event handler not found');
                        return;
                    }
                    handler.callback.apply(handler.target, [...handler.args, event]);
                }, this);
            }
        }
        Node.prototype.onEvent = function (type: NodeEventType, callback: Function, target?: any, ...args: any) {
            // 使用WeakMap获取节点对应的事件映射
            if (!nodeEventRegistry.has(this)) {
                nodeEventRegistry.set(this, new Map());
            }
            const eventMap = nodeEventRegistry.get(this)!;
            // 生成唯一标识符（事件类型+）
            const eventKey = Symbol(`${type.toString()}_${callback.name || 'anonymous'}`);
          
            if (eventMap.has(eventKey)) return;
            // 生成基于类型和回调的唯一标识符
            const handler = (event: Event) => {
                callback && callback.apply(target || this, [...args, event]);
            };
            // 存储到WeakMap
            eventMap.set(eventKey, {
                callback: handler,
                target: target || this,
                type: type,
                args: args || []
            });
            // 注册原生事件
            this.on(type, handler, target || this);
        }
        // 配套的offEvent方法
        Node.prototype.offEvent = function (type: NodeEventType, callback: Function) {
            const eventMap = nodeEventRegistry.get(this);
            if (!eventMap) return;

            // 遍历查找对应事件类型和回调
            eventMap.forEach((value, key) => {
                if (value.callback === callback) {  // 改为比较存储的handler
                    this.off(type, value.callback, value.target);
                    eventMap.delete(key);
                }
            });
        }

        // 新增 offAllEvent 方法
        Node.prototype.offAllEvent = function () {
            const eventMap = nodeEventRegistry.get(this);
            if (!eventMap) return;
            // 遍历所有已注册事件
            eventMap.forEach((value, key) => {
                // 从 eventKey 的描述中解析事件类型（例如 "TOUCH_START_onTouchStart" 取前半部分）
                const typeStr = key['description']?.split('_')[0] || '';
                const type = typeStr as NodeEventType;
                // 解绑事件并删除记录
                this.off(type, value.callback, value.target);
                eventMap.delete(key);
            });
        };
        Node.prototype.offClick = function (callback: Function, target: any) {
            if (this.eventMap.has(callback)) {
                this.off('click', callback, target);
                this.eventMap.delete(callback);
            }
        }
        Node.prototype.offAllClick = function () {
            if(this.eventMap){
                this.eventMap.forEach((target, callback) => {
                    this.off('click', callback, target);
                })
                this.eventMap.clear(); // 清空 eventMap
            }
        }
        Node.prototype.startShake = function (shakeDuration: number, shakeStrength: number) {
            const startTime = sys.now();
            const endTime = startTime + shakeDuration * 1000;
            this['oldPos'] = this['oldPos'] ? this['oldPos'] : this.getPosition();
            const originalPosition = this['oldPos']
            const shakeTween = tween(this)
                .call(() => {
                    if (sys.now() < endTime) {
                        const randomX = (Math.random() - 0.5) * 2 * shakeStrength;
                        const randomY = (Math.random() - 0.5) * 2 * shakeStrength;
                        this.setPosition(
                            new Vec3(originalPosition.x + randomX, originalPosition.y + randomY, originalPosition.z)

                        );
                    } else {
                        this.setPosition(originalPosition);
                        shakeTween.stop();
                    }
                })
                .delay(0.01)
                .union()
                .repeatForever()
                .start();
        }
        Node.prototype['__destroy']= Node.prototype.destroy;
        Node.prototype['destroy'] = function () {
            // this.children.forEach((child) => {
                
            // })
            this.offAllEvent()
            this.offAllClick()
            if (this['shakeTween']) {
                this['shakeTween'].stop(); 
            }
            return this['__destroy'].call(this);
        }
    }
}
export interface DeviceInfo {
    userAgent: string;
    screenWidth: number;
    screenHeight: number;
    language: string;
}

